home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 33.4 KB | 1,225 lines | [TEXT/MPS ] |
- // UTECommands.cp
- // Copyright © 1984-1991 Apple Computer Inc. All rights reserved.
-
- #ifndef __STDIO__
- #include <StdIo.h>
- #endif
-
- #ifndef __UGEOMETRY__
- #include <UGeometry.h>
- #endif
-
- #ifndef __ULIST__
- #include <UList.h>
- #endif
-
- #ifndef __ALIASES__
- #include <Aliases.h>
- #endif
-
- #ifndef __UFILE__
- #include <UFile.h>
- #endif
-
- #ifndef __EDITIONS__
- #include <Editions.h>
- #endif
-
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- #ifndef __UAPPLICATION__
- #include <UApplication.h>
- #endif
-
- #ifndef __UDOCUMENT__
- #include <UDocument.h>
- #endif
-
- #ifndef __USCROLLER__
- #include <UScroller.h>
- #endif
-
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
-
- #ifndef __UCLIPBOARDMGR__
- #include <UClipboardMgr.h>
- #endif
-
- #ifndef __UPRINTHANDLER__
- #include <UPrintHandler.h>
- #endif
-
- #ifndef __UFAILURE__
- #include <UFailure.h>
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include <UMacAppUtilities.h>
- #endif
-
- #ifndef __UPATCH__
- #include <UPatch.h>
- #endif
-
- #ifndef __UMEMORY__
- #include <UMemory.h>
- #endif
-
- #ifndef __UMACAPPGLOBALS__
- #include <UMacAppGlobals.h>
- #endif
-
- #ifndef __UERRORMGR__
- #include <UErrorMgr.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __UMENUMGR__
- #include <UMenuMgr.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #ifndef __FONTS__
- #include <Fonts.h>
- #endif
-
- #ifndef __SCRIPT__
- #include <Script.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #include "UTECommands.h"
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEFields
-
- pascal void DumpTTECommand(TTECommand* theTTECommand)
- {
- long oldStyleSize;
- long newStyleSize;
- long last;
-
- fprintf(stderr, "old start/end, new start/end, diff :%1d/%1d, %1d/%1d, %1d \n",
- theTTECommand->fOldStart, theTTECommand->fOldEnd,
- theTTECommand->fNewStart, theTTECommand->fNewEnd,
- Max(Max(theTTECommand->fOldEnd - theTTECommand->fOldStart, 0),
- Max(theTTECommand->fNewEnd - theTTECommand->fNewStart, 0)));
- fprintf(stderr, "fTextPad :%1d\n", theTTECommand->fTextPad);
- fprintf(stderr, "fPadding size :%1d\n", GetHandleSize(theTTECommand->fPadding));
-
- oldStyleSize = 0;
- newStyleSize = 0;
- fprintf(stderr, "** Old styles:\n");
- if (theTTECommand->fOldStyles == NULL)
- fprintf(stderr, "NONE!\n");
- else
- {
-
- last = (**(theTTECommand->fOldStyles)).scrpNStyles;
- fprintf(stderr, "Number of table entries: %1d\n", last);
- for (long i = 0; i <= last - 1; ++i)
- {
- ScrpSTElement & theScrpSTElement = (**(theTTECommand->fOldStyles)).scrpStyleTab[i];
-
- fprintf(stderr, "%1d, ofs:%1d ", theScrpSTElement.scrpStartChar);
- //!!! WrLblField(AtStr(''), &scrpFont, bStyle);
- fprintf(stderr, "\n");
- }
- oldStyleSize = GetHandleSize((Handle)(theTTECommand->fOldStyles));
- }
-
- fprintf(stderr, "** New styles:\n");
- if (theTTECommand->fNewStyles == NULL)
- fprintf(stderr, "NONE!\n");
- else
- {
- last = (**(theTTECommand->fNewStyles)).scrpNStyles;
- fprintf(stderr, "Number of table entries: %1d\n", last);
- for (long i = 0; i <= last - 1; ++i)
- {
- ScrpSTElement & theScrpSTElement = (**(theTTECommand->fNewStyles)).scrpStyleTab[i];
-
- fprintf(stderr, "%1d, ofs:%1d ", theScrpSTElement.scrpStartChar);
- //!!! WrLblField(AtStr(''), &scrpFont, bStyle);
- fprintf(stderr, "\n");
- }
- newStyleSize = GetHandleSize((Handle)(theTTECommand->fNewStyles));
- }
-
- fprintf(stderr, "Styles size diff: %1d\n", Max(newStyleSize, oldStyleSize));
- fprintf(stderr, "fStylePad :%1d\n", theTTECommand->fStylePad);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TESelCommand
- pascal void TTECommand::Initialize(void) // override
- {
- inherited::Initialize();
-
- fHTE = NULL;
- fNewEnd = 0;
- fNewStart = 0;
- fNewStyles = NULL;
- fNewText = NULL;
- fOldEnd = 0;
- fOldStart = 0;
- fOldStyles = NULL;
- fOldText = NULL;
- fPadding = NULL;
- fStylePad = 0;
- fTEView = NULL;
- fTextPad = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TESelCommand
-
- pascal void TTECommand::ITECommand(TTEView* itsTEView,
- CmdNumber itsCmdNumber,
- Boolean itsSaveText)
- {
- short selChars;
- Handle h;
- FailInfo fi;
-
- this->ICommand(itsCmdNumber, itsTEView->fDocument, itsTEView);
- fTEView = itsTEView;
- fHTE = itsTEView->fHTE;
-
- {
- TERec & theTERec = **fHTE;
-
- fOldStart = theTERec.selStart;
- fOldEnd = theTERec.selEnd;
- selChars = theTERec.selEnd - theTERec.selStart;
- }
-
- if (fi.Try())
- {
- if (itsSaveText)
- {
- h = NewPermHandle(selChars);
-
- if (selChars > 0)
- BlockMove((Ptr)((*((**fHTE).hText)) + fOldStart), (*h), selChars);
-
- fOldText = h;
- fTextPad = fOldStart - fOldEnd;
- fPadding = NewPermHandle(0);
- }
-
- /* TextEdit has this "feature" which it exercises if it runs out of memory. It's
- called DS number 25. We'll try to avoid it by assuring that enough memory exists
- to fulfill the request, but we won't die because of it. This is a particularly
- ugly situation - there could be >600K of style information associated with a 32K
- block of text. And to support undo, we've got to assume that there may momentarily
- be THREE copies floating around, adding up to a total potential liability of almost
- 2 Meg for a single TE record. The worst that can happen, though, is that the text
- will be safe, but it won't have any styles associated with it. */
-
- if ((itsTEView->fStyleType == kWithStyle) && itsTEView->SpaceForStyles((**fHTE).selStart, (**fHTE).selEnd))
- {
- fOldStyles = GetStylScrap(fHTE);
- FailNIL(fOldStyles);
- fStylePad = GetHandleSize((Handle)fOldStyles);
- }
-
- fi.Success();
- }
- else // Recover
- {
- this->Free();
- fi.ReSignal();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::Free(void) // override
- {
- fOldText = DisposeIfHandle(fOldText);
- fOldStyles = (StScrpHandle)DisposeIfHandle((Handle)fOldStyles);
- fNewText = DisposeIfHandle(fNewText);
- fNewStyles = (StScrpHandle)DisposeIfHandle((Handle)fNewStyles);
- fPadding = DisposeIfHandle(fPadding);
-
- inherited::Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::BanishOldText(void)
- {
- if (fOldEnd > fOldStart)
- TEDelete(fHTE);
- SetHandleSize(fPadding, Max(-(fTextPad + fStylePad), 0));
- FailMemError();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::InstallNewText(void)
- {
- long savedSize;
- Handle itsText;
- SignedByte savedState;
-
-
- if (fNewEnd > fNewStart)
- {
- itsText = fTEView->fText;
- savedSize = GetHandleSize(itsText);
-
- #if qDebug
- if (fNewText == NULL)
- ProgramBreak("InstallNewText called with fNewText == NULL!");
- #endif
-
- savedState = LockHandleHigh(fNewText); // Prevent heap fragmentation for TEInsert
-
- if (fTEView->fStyleType == kWithStyle) // If record has style, use it
- TEStylInsert((*fNewText), // It's okay for fNewStyles to be NULL here
- GetHandleSize(fNewText), fNewStyles, fHTE);
- else // Otherwise, do it the old-fashioned way
- TEInsert((*fNewText), GetHandleSize(fNewText), fHTE);
-
- HSetState(fNewText, savedState);
-
- if (GetHandleSize(itsText) <= savedSize)
- FailOSErr(memFullErr);
-
- fTEView->fSpecsChanged = TRUE;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEFields
-
- pascal void TTECommand::Fields(TObject* obj) // override
- {
- obj->DoToField("TTECommand", (Ptr)NULL, bClass);
- obj->DoToField("fTEView", (Ptr) & fTEView, bObject);
- obj->DoToField("fHTE", (Ptr) & fHTE, bTEHandle);
- obj->DoToField("fOldStart", (Ptr) & fOldStart, bInteger);
- obj->DoToField("fOldEnd", (Ptr) & fOldEnd, bInteger);
- obj->DoToField("fOldText", (Ptr) & fOldText, bHandle);
- obj->DoToField("fOldStyles", (Ptr) & fOldStyles, bHandle);
- obj->DoToField("fNewStart", (Ptr) & fNewStart, bInteger);
- obj->DoToField("fNewEnd", (Ptr) & fNewEnd, bInteger);
- obj->DoToField("fNewText", (Ptr) & fNewText, bHandle);
- obj->DoToField("fNewStyles", (Ptr) & fNewStyles, bHandle);
- obj->DoToField("fPadding", (Ptr) & fPadding, bHandle);
- obj->DoToField("fTextPad", (Ptr) & fTextPad, bInteger);
- obj->DoToField("fStylePad", (Ptr) & fStylePad, bLongInt);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::RemoveAdditions(void)
- {
- if (fNewText != NULL)
- {
- TESetSelect(fNewStart, fNewEnd, fHTE);
- TEDelete(fHTE);
- }
- SetHandleSize(fPadding, Max(fTextPad + fStylePad, 0));
- FailMemError();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::RestoreSelection(void)
- {
- TESetSelect(fOldStart, fOldEnd, fHTE);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::ReviveDeletions(void)
- {
- Handle itsText;
- long savedSize;
- short nChars;
- SignedByte savedState;
-
-
- TESetSelect(fOldStart, fOldStart, fHTE); // so insert will take place at right point
- nChars = (short)GetHandleSize(fOldText); //!!! long->short
- if (nChars > 0)
- {
- itsText = fTEView->fText;
- savedSize = GetHandleSize(itsText);
-
- savedState = LockHandleHigh(fOldText); // Prevent heap fragmentation
-
- if (fTEView->fStyleType == kWithStyle) // If record has style, use it
- TEStylInsert((*fOldText), nChars, // It's okay for fOldStyles to be NULL here
- fOldStyles, fHTE);
- else // Otherwise, do it the old-fashioned way
- TEInsert((*fOldText), nChars, fHTE);
-
- HSetState(fOldText, savedState);
-
- if (GetHandleSize(itsText) <= savedSize)
- FailOSErr(memFullErr);
-
- fTEView->fSpecsChanged = TRUE;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::DoMainFunction(void)
- {
- if (fID != cCopy)
- this->BanishOldText();
- this->InstallNewText();
- if (fID != cCopy)
- fTEView->SynchView(kRedraw);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::DoIt(void) // override
- {
- fTEView->Focus(); //??? What if Focus fails
-
- this->DoMainFunction();
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::UndoIt(void) // override
- {
- fTEView->Focus(); //??? What if Focus fails
-
- this->RemoveAdditions();
- this->ReviveDeletions();
- this->RestoreSelection();
- if (fID != cCopy)
- fTEView->SynchView(kRedraw);
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECommand::RedoIt(void) // override
- {
- fTEView->Focus(); //??? What if Focus fails
-
- this->RestoreSelection();
- this->DoMainFunction();
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TESelCommand
-
- pascal void TTECutCopyCommand::ITECutCopyCommand(TTEView* itsTEView,
- CmdNumber itsCmdNumber)
- {
- fClipCreated = FALSE;
- this->ITECommand(itsTEView, itsCmdNumber, TRUE);
- fChangesClipboard = TRUE;
- fCausesChange = (itsCmdNumber != cCopy);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECutCopyCommand::Free(void) // override
- {
- if (fClipCreated)
- fOldText = NULL;
- inherited::Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECutCopyCommand::DoIt(void) // override
- {
- //TTECutCopyCommand.DoIt
- TTEView * clipTEView;
- FailInfo fi;
- TextStyle clipStyle;
- VPoint itsSize;
- VRect itsMargins;
-
- VOLATILE(clipTEView);
-
- fTEView->Focus(); //??? What if Focus fails
-
- SetTextStyle(clipStyle, applFont, 0, 12, gRGBBlack);// Initial style same as virgin TEView
-
- itsSize = VPoint(50, 100); // An arbitrary initial size.
- itsMargins = VRect(8, 10, 0, 10); // No bottom margin.
-
- clipTEView = new TTEView; // Create a new view for the clipboard
- clipTEView->ITEView(NULL, NULL, // Initialize view
- gZeroVPt, itsSize, sizeSuperView, sizeVariable, itsMargins, clipStyle, teFlushDefault, fTEView->fStyleType, fTEView->fAutoWrap);
- clipTEView->fAcceptsChanges = FALSE; // This is a read-only view
-
- // Cut can eat into temp memory so users can rescue text from overweight documents
- if (fi.Try())
- {
- if (!fCausesChange) // If Copy-ing, assure there's enough room
- FailSpaceIsLow();
- fi.Success();
- }
- else // Recover
- {
- clipTEView = (TTEView *)(FreeIfObject(clipTEView));
- fi.ReSignal();
- }
-
- clipTEView->StuffText(fOldText);
- FailSpaceIsLow();
-
- //??? GOT TO FIGURE OUT SOME WAY TO PRE-FLIGHT THIS! ???????????????????????????????????
- if (clipTEView->fStyleType == kWithStyle) // If record has style
- SetStylScrap(0, MAXINT, fOldStyles, // …then put in the styles
- kDontRedraw, clipTEView->fHTE);
- FailSpaceIsLow();
-
- clipTEView->fFreeText = TRUE; // Let TEView know it has to free the text
-
- gClipboardMgr->ClaimClipboard(clipTEView); // Okay to claim (will call RecalcText!)
-
- fClipCreated = TRUE; // We be done
- this->DoMainFunction(); // Do the actual cut/copy
-
- #if qDebug
- if (pTEIntenseDebugging)
- {
- DumpTERecord(clipTEView->fHTE);
- DumpTTECommand(this);
- }
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTECutCopyCommand::ReviveDeletions(void)// override
- {
- if (fID == cCut)
- inherited::ReviveDeletions(); // Don't do it for COPY
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEFields
-
- pascal void TTECutCopyCommand::Fields(TObject* obj)// override
- {
- obj->DoToField("TTECutCopyCommand", (Ptr)NULL, bClass);
- obj->DoToField("fClipCreated", (Ptr) & fClipCreated, bBoolean);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TESelCommand
-
- pascal void TTEPasteCommand::ITEPasteCommand(TTEView* itsTEView)
- /* We can't use TEPaste because it clobbers the DeskScrap; the text would be recoverable
- from the special TextEdit Scrap, but other types of non-TEXT scrap are permanently
- lost, it seems */
-
- {
- Boolean savedPerm;
- short newLength;
- long newStyleLen;
- Handle newText;
- StScrpHandle newStyles;
- ResType dataType = '%%%%';
- FailInfo fi;
-
- VOLATILE(newText);
- VOLATILE(newStyles);
-
- this->ITECommand(itsTEView, cPaste, TRUE); // Perform stock initializations
-
- savedPerm = FALSE;
-
- newStyleLen = 0; // Assume there are no new styles
- newStyles = NULL;
- newText = NULL;
-
- if (fi.Try())
- {
- newText = NewPermHandle(0); // Create handle to receive clipboard data
- if (itsTEView->fStyleType == kWithStyle)
- {
- newStyles = StScrpHandle(NewPermHandle(0));// Same for handle to receive style info
- }
-
- //!!! dataType is not used by GetDataToPaste. should it really be parameter?
- newLength = (short)gClipboardMgr->GetDataToPaste(newText, dataType);//!!! long->short
-
- if (newLength > 0)
- {
- #if qDebug
- if (dataType != 'TEXT')
- ProgramBreak("TEPasteCommand given some non-text from clipboard");
- else
- #endif
-
- { // Prime "new" values
- fNewText = newText;
- fNewStart = (**fHTE).selStart;
- fNewEnd = fNewStart + newLength;
- fTextPad = newLength - (fOldEnd - fOldStart);
-
- if (itsTEView->fStyleType == kWithStyle)
- {
- newStyleLen = gClipboardMgr->fClipView->GivePasteData(Handle(newStyles), 'styl');
- if (newStyleLen > 0)
- {
- fNewStyles = newStyles;
- fStylePad = // Difference between old and new styles
- newStyleLen - fStylePad;
- }
- else
- newStyles = (StScrpHandle)DisposeIfHandle((Handle)newStyles);
- }
-
- SetPermHandleSize(fPadding, Max(fTextPad + fStylePad, 0));
-
- FailSpaceIsLow();
- }
- }
- else
- {
- newText = DisposeIfHandle(newText);
- newStyles = (StScrpHandle)DisposeIfHandle((Handle)newStyles);
- }
- fi.Success();
- }
- else // Recover
- {
- if (newText != fNewText) // newText is assigned to fNewText
- newText = DisposeIfHandle(newText); // …so avoid disposing twice.
- if (newStyles != fNewStyles) // Ditto for newStyles.
- newStyles = (StScrpHandle)DisposeIfHandle((Handle)newStyles);
- this->Free();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEFields
-
- pascal void TTEPasteCommand::Fields(TObject* obj)// override
- {
- obj->DoToField("TTEPasteCommand", (Ptr)NULL, bClass);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TESelCommand
-
- pascal void TTEStyleCommand::ITEStyleCommand(TTEView* itsTEView,
- const TextStyle& itsNewStyle,
- CmdNumber itsCmdNumber,
- short itsMode)
- {
- FailInfo fi;
-
- this->ITECommand(itsTEView, itsCmdNumber, FALSE);// Perform stock initialization, sans text
-
- fOldTextStyle = itsTEView->fTextStyle;
- fNewTextStyle = itsNewStyle;
-
- // Only do color change if we can
- if (qNeedsColorQD || gConfiguration.hasColorQD)
- fMode = itsMode;
- else
- fMode = itsMode &~doColor;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTEStyleCommand::InstallOneStyle(const TextStyle& newStyl)
- {
- fTEView->SetOneStyle(fOldStart, fOldEnd, fMode, newStyl, kRedraw);// Focus'es for us
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTEStyleCommand::InstallManyStyles(StScrpHandle newStyls)
- {
- fTEView->Focus();
- // No need to check for fStyleType, since we only get here if the record is stylish
- SetStylScrap(fOldStart, fOldEnd, newStyls, kRedraw, fHTE);
- fTEView->RecalcText(); // Might have changed number of lines
- fTEView->SynchView(kRedraw); // Show corrected view
-
- fTEView->fSpecsChanged = TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTEStyleCommand::DoIt(void) // override
- {
- TextStyle aTextStyle;
-
- aTextStyle = fNewTextStyle;
- this->InstallOneStyle(aTextStyle);
- fMode = fMode &~doToggle; // fMode = BAND(fMode, BNOT(doToggle));// Turn off toggle mode, if set
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTEStyleCommand::UndoIt(void) // override
- {
- TextStyle aTextStyle;
-
- this->RestoreSelection();
-
- if (fTEView->fStyleType == kWithoutStyle)
- {
- aTextStyle = fOldTextStyle;
- this->InstallOneStyle(aTextStyle);
- }
- else
- this->InstallManyStyles(fOldStyles);
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTEStyleCommand::RedoIt(void) // override
- {
- this->RestoreSelection();
- this->DoIt();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEFields
-
- pascal void TTEStyleCommand::Fields(TObject* obj)// override
- {
- obj->DoToField("TTEStyleCommand", (Ptr)NULL, bClass);
- obj->DoToField("fMode", (Ptr) & fMode, bInteger);
- obj->DoToField("fOldTextStyle", (Ptr) & fOldTextStyle, bTextStyle);
- obj->DoToField("fNewTextStyle", (Ptr) & fNewTextStyle, bTextStyle);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- pascal void TTETypingCommand::ITETypingCommand(TTEView* itsTEView,
- short itsFirstChar)
- {
- FailInfo fi;
-
- this->ITECommand(itsTEView, cTyping, TRUE);
-
- if (fi.Try())
- {
-
- fNewStart = (**fHTE).selStart; // Start and end are the same
- fNewEnd = fNewStart;
-
- fNewText = NULL;
- fNewText = NewPermHandle(0); // Allocate an empty block for text
-
- fCompleted = FALSE; // We've only just begun…
- fFirstChar = itsFirstChar; // Save character for Doit
- fi.Success();
- }
- else // Recover
- {
- this->Free();
- fi.ReSignal();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- pascal void TTETypingCommand::Free(void) // override
- {
- if (fTEView->fTypingCommand == this)
- fTEView->fTypingCommand = NULL;
- inherited::Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- pascal void TTETypingCommand::DoNormalChar(short aChar)
- {
- FailOSErr(PtrAndHand((Ptr)((&aChar) + 1), // Append char to end of fNewText
- fNewText, 1));
- ++fNewEnd; // Bump both end of "selection"
- ++fTextPad; // …and padding value
-
- SetHandleSize(fPadding, /* This SetHandleSize can't grow the handle,
- */Max(-(fTextPad + fStylePad), 0));// …so it shouldn't fail.
- FailMemError();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- //!!!
- typedef TextStyle* TSPtr;
-
- // User has backspaced to the left of the original starting point. First, copy the
- // character (which may be more than one byte long if we are using a non-Roman script) to
- // a temporary buffer. The assumption is that no character will ever be longer than four
- // bytes. Sorry, folks, MacApp does not support typing in any script with more than 4
- // billion characters. Next, copy the character to the front of fOldText, and adjust
- // fOldStart, fNewStart, and fNewEnd. Note that we do !check for MemSpaceIsLow, since we
- // want to let the user delete characters.
- pascal void TTETypingCommand::BkSpcLeft(Handle theText,
- short curStart)
- {
- short savedSize;
- short theHeight;
- short theAscent;
- long oldSize;
- TSPtr aTextStyle;
- char savedChar[4]; //Pascal: savedChar: PACKED ARRAY [0..3] OF Char;
- TextStyle delStyle;
-
- savedSize = 1;
- while (CharByte((*theText), curStart - savedSize) > 0)
- ++savedSize;
- curStart -= savedSize;
-
- #if qDebug
- if (savedSize > 4)
- ProgramBreak("Character > 4 bytes");
- #endif
-
- if (savedSize == 1) /* Slight speed optimization for normal case
- */
- savedChar[0] = (*((CharsHandle)theText))[curStart];
- else
- BlockMove((Ptr)((*theText) + curStart), (Ptr)savedChar, savedSize);
-
- if (fTEView->fStyleType == kWithStyle) // Only do this if styles are around
- {
- TEGetStyle(curStart, delStyle, // Get the style of the deleted character
- theHeight, theAscent, fHTE); // (1 or 4 bytes, it's all only one style)
-
- if (!EqualBlocks((Ptr) & delStyle, // If style doesn't match first in the list
- (Ptr) & ((**fOldStyles).scrpStyleTab[0].scrpFont), sizeof(TextStyle)))
- {
- // …then insert new style at head of list
- fTEView->fSpecsChanged = TRUE; // User backspaced into new style!
-
- oldSize = // Make room for the new style element
- GetHandleSize(Handle(fOldStyles));
- SetHandleSize(Handle(fOldStyles), oldSize + sizeof(ScrpSTElement));
- FailMemError();
- fStylePad += sizeof(ScrpSTElement);
-
- {
- ScrpSTElement & theScrpSTElement = (**fOldStyles).scrpStyleTab[0];
-
- BlockMove((Ptr) & (theScrpSTElement.scrpStartChar),// Move entire array up one element's size
- (Ptr)(&(theScrpSTElement.scrpStartChar) + sizeof(ScrpSTElement)), oldSize - sizeof((**fOldStyles).scrpNStyles));
- }
-
- (**fOldStyles).scrpNStyles++;// One more style
-
- {
- ScrpSTElement & theScrpSTElement = (**fOldStyles).scrpStyleTab[0];
-
- theScrpSTElement.scrpHeight = theHeight;// Fill in the blanks
- theScrpSTElement.scrpAscent = theAscent;
- aTextStyle = (TSPtr)(&theScrpSTElement.scrpFont);
- (*aTextStyle) = delStyle;
- }
- }
-
- (**fOldStyles).scrpStyleTab[0].scrpStartChar--;// Regardless, back off offset by one
- }
-
- SetHandleSize(fPadding, GetHandleSize(fOldText) + savedSize + fStylePad);
- FailMemError();
- Munger(fOldText, 0, NULL, 0, (Ptr)savedChar, savedSize);
- FailMemError();
- fOldStart = curStart; // Treat this as though original selection
- fNewStart = curStart; // …had included this character
- fNewEnd = curStart;
- fTextPad -= savedSize;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- pascal void TTETypingCommand::BkSpcRight(Handle theText,
- short curStart)
- {
- short savedSize;
-
-
- savedSize = 1;
- while (CharByte((*theText), curStart - savedSize) > 0)
- ++savedSize;
- SetHandleSize(fPadding, Max(-(fTextPad - savedSize + fStylePad), 0));
- FailMemError();
- fNewEnd -= savedSize;
- fTextPad -= savedSize;
-
- SetHandleSize(fNewText, fNewEnd - fNewStart);/* Shouldn't fail as we're only shrinking it
- */
- FailMemError();
- }
-
- //--------------------------------------------------------------------------------------------------
- // Forward delete courtesy of: Larry Goldman. Used by permission.
- #pragma segment TERes
-
- pascal void TTETypingCommand::FwdDelete(Handle theText,
- short curStart,
- short curEnd)
- {
- short savedSize;
- short theHeight;
- short theAscent;
- long oldSize;
- TSPtr aTextStyle;
- char savedChar[3];
- TextStyle delStyle;
- long textSize;
- long oldTextSize;
-
- textSize = GetHandleSize(theText);
- if ((curStart == curEnd) && (curStart < textSize))
- {
-
- savedSize = 0; //Get the complete character
- while ((curStart + savedSize <= textSize) && (CharByte((*theText), curStart + savedSize) > 0))
- ++savedSize;
- ++savedSize;
- #if qDebug
- if (savedSize > 4)
- ProgramBreak("Character > 4 bytes");
- #endif
-
- if (savedSize == 1) // Slight speed optimization for normal case
- savedChar[0] = (*((CharsHandle)theText))[curStart];
- else
- BlockMove((Ptr)((*theText) + curStart), (Ptr)savedChar, savedSize);
-
- if ((curStart >= fNewStart) && (curStart < fNewEnd))// char is within fNewText
- {
- /*Remove the char from fNewText and update
- fNewEnd and fTextPad*/
- SetHandleSize(fPadding, Max(-(fTextPad - savedSize + fStylePad), 0));
- FailMemError();
- fNewEnd -= savedSize;
- fTextPad -= savedSize;
-
- // Shouldn't fail as we're only shrinking it
- Munger(fNewText, curStart - fNewStart, NULL, savedSize, (Ptr)savedChar, 0);
- FailMemError();
- }
- else /* add char to the end of fOldChars, don't
- update fOldEnd, but update fPadding*/
- {
- oldTextSize = GetHandleSize(fOldText);
- if (fTEView->fStyleType == kWithStyle)// Only do this if styles are around
- {
- TEGetStyle(curStart, delStyle, // Get the style of the deleted character
- theHeight, theAscent, fHTE);// (1 or 4 bytes, it's all only one style)
-
- if (!EqualBlocks((Ptr) & delStyle,// If style doesn't match last in the list
- (Ptr) & (**fOldStyles).scrpStyleTab[(**fOldStyles).scrpNStyles - 1].scrpFont, sizeof(TextStyle)))
- {
- // …then insert new style at end of list
- fTEView->fSpecsChanged = TRUE;// User backspaced into new style!
-
- oldSize = GetHandleSize((Handle)fOldStyles);// Make room for the new style element
- SetHandleSize((Handle)fOldStyles, oldSize + sizeof(ScrpSTElement));
- FailMemError();
- fStylePad = fStylePad + sizeof(ScrpSTElement);
-
- (**fOldStyles).scrpNStyles++;// One more style
-
- {
- ScrpSTElement & theScrpSTElement = (**fOldStyles).scrpStyleTab[(**fOldStyles).scrpNStyles - 1];
-
- theScrpSTElement.scrpStartChar = oldTextSize;
- theScrpSTElement.scrpHeight = theHeight;// Fill in the blanks
- theScrpSTElement.scrpAscent = theAscent;
- aTextStyle = (TSPtr) & theScrpSTElement.scrpFont;
- (*aTextStyle) = delStyle;
- }
- }
- }
-
- SetHandleSize(fPadding, oldTextSize + savedSize + fStylePad);
- FailMemError();
- Munger(fOldText, oldTextSize, NULL, 0, (Ptr)savedChar, savedSize);
- FailMemError();
- fTextPad = fTextPad - savedSize;
-
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- /* ??? All this handle munging is expensive. Better would be to accumulate memory in
- "chunks" of, say, 16 bytes so that this checking need not happen every time through.
- Fortunately, the normal cases are not that bad. */
- #pragma segment TERes
-
- pascal void TTETypingCommand::AddCharacter(short aChar)
- {
- Handle theText;
- short curSelStart;
- short curSelEnd;
- Boolean savedPerm;
- FailInfo fi;
-
- VOLATILE(savedPerm);
-
- fView->Update(); /* Makes sure that all of TE's actions are
- Visible */
- fView->Focus();
-
- {
- TERec & theTERec = **fHTE;
-
- curSelStart = theTERec.selStart;
- curSelEnd = theTERec.selEnd;
- theText = theTERec.hText;
- }
- if (fi.Try())
- {
- savedPerm = PermAllocation(TRUE);
-
- /* Update the fNewText handle and other information. Note that because of backspace,
- this can be tricky.*/
-
- if (aChar == chFwdDelete) // User types forward delete, so keep in synch
- this->FwdDelete(theText, curSelStart, curSelEnd);
-
- else if (aChar != chBackspace) // Not a backspace. Do the right thing
- this->DoNormalChar(aChar);
-
- else if ((curSelStart <= fOldStart) && (curSelStart > 0) && (curSelStart == curSelEnd))// User typed backspace so keep in synch
- this->BkSpcLeft(theText, curSelStart); // Handle backspace to left of start
-
- else if (fNewEnd > fNewStart) // Delete 1 character from end of fNewText
- this->BkSpcRight(theText, curSelStart); // Handle backspace to right of start
-
- savedPerm = PermAllocation(savedPerm);
- fi.Success();
- }
- else // Recover
- {
- savedPerm = PermAllocation(savedPerm);
- fi.ReSignal();
- }
-
-
- if (aChar != chFwdDelete)
- /* Let TextEdit have the character, as either 1) we're adding a byte, so we know there
- is a reserve tank, so the worst this will do is eat into it a little, or 2) we're
- deleting a character, which can only decrease memory usage. */
- TEKey(aChar, fHTE);
- else if (curSelStart != curSelEnd) // forward delete with chars selected
- TEDelete(fHTE);
- else if (curSelStart < GetHandleSize(theText))
- {
- // forward delete with insertion point
- TEKey(chRight, fHTE);
- TEKey(chBackspace, fHTE);
- }
-
- fTEView->SynchView(kRedraw); // Now clean up the view.
-
- #if qDebugMsg
- if (pTEIntenseDebugging)
- {
- WrLblHandleContents("fOldText", fOldText);
- fprintf(stderr, "\n");
- WrLblHandleContents("fNewText", fNewText);
- fprintf(stderr, "\n");
- DumpTTECommand(this);
- }
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- pascal void TTETypingCommand::DoIt(void) // override
-
- {
- this->AddCharacter(fFirstChar);
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
-
- #pragma segment TEDoCommand
-
- pascal void TTETypingCommand::RedoIt(void) // override
-
- {
- TextStyle currentStyle;
- short lineHeight;
- short fontAscent;
- Boolean resetStyle;
-
-
- if ((fOldEnd - fOldStart) == GetHandleSize(fOldText))
- {
- // No chars were vacuumed
- resetStyle = FALSE;
- if ((fTEView->fStyleType == kWithStyle) && (fOldEnd == fOldStart))
- {
- TEGetStyle(fOldStart, currentStyle, lineHeight, fontAscent, fHTE);
- resetStyle =!EqualBlocks((Ptr) & currentStyle, (Ptr) & (*fOldStyles)->scrpStyleTab[0].scrpFont, sizeof(TextStyle));
- }
-
- if (resetStyle) // The new text has a style of its own
- fNewStyles = fOldStyles; // Make InstallNewText insert styles, too
- inherited::RedoIt();
- if (resetStyle)
- fNewStyles = NULL; // So fNewStyles doesn't get disposed
- }
- else
- {
- fTEView->Focus(); //??? What if Focus fails
- TESetSelect(fOldStart, fOldStart + GetHandleSize(fOldText), fHTE);/* select vacuumed chars,
- too */
- TEDelete(fHTE); // Remove old text, including vacuumed chars
- SetHandleSize(fPadding, Max(-(fTextPad + fStylePad), 0));
- FailMemError();
- this->InstallNewText();
- fTEView->SynchView(kRedraw);
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEDoCommand
-
- pascal void TTETypingCommand::UndoIt(void) // override
- {
- this->CompleteTyping();
- inherited::UndoIt();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TERes
-
- pascal void TTETypingCommand::CompleteTyping(void)
- {
- long offset;
-
-
- fCompleted = TRUE;
-
- if (fTEView->fStyleType == kWithStyle)
- {
- StScrpRec & theStScrpRec = **fOldStyles;
- {
- offset = -theStScrpRec.scrpStyleTab[0].scrpStartChar;
- if (offset > 0)
- for (short i = 0; i <= theStScrpRec.scrpNStyles - 1; ++i)
- theStScrpRec.scrpStyleTab[i].scrpStartChar += offset;
- }
- }
- #if qDebug
- if (pTEIntenseDebugging)
- DumpTTECommand(this);
- #endif
-
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment TEFields
-
- pascal void TTETypingCommand::Fields(TObject* obj)// override
- {
- obj->DoToField("TTETypingCommand", (Ptr)NULL, bClass);
- obj->DoToField("fCompleted", (Ptr) & fCompleted, bBoolean);
- obj->DoToField("fFirstChar", (Ptr) & fFirstChar, bBoolean);
-
- inherited::Fields(obj);
- }
-
-